<?php

namespace app\service;

use Alipay\EasySDK\Kernel\Exceptions\RuntimeException;
use Alipay\EasySDK\Kernel\Factory;
use Alipay\EasySDK\Kernel\Config;
use app\common\PayStatus;
use app\common\VipStatus;
use app\model\UserVip;
use app\model\VipOrder;
use Exception;
use support\Log;

class AlipayService
{

    public static ?AlipayService $_instance = null;

    /**
     * @return AlipayService|mixed
     */
    public static function instance(): ?AlipayService
    {
        if (!static::$_instance) static::$_instance = new self();
        return static::$_instance;
    }

    /**
     * 另一套配置
     * notifyUrl WEB_URL . "/h5/payCallback/alipay/"
     */
    public function __construct()
    {
        $options              = new Config();
        $options->protocol    = 'https';
        $options->gatewayHost = 'openapi.alipay.com';
        $options->signType    = 'RSA2';
        $options->appId       = '20210031946';
        // 为避免私钥随源码泄露，推荐从文件中读取私钥字符串而不是写入源码中
        $options->merchantPrivateKey = 'MIIEpAIBAAKCAQEAlhvnjG/joNBd2+TsfX++gx2PuRbK0dufB8p96/==';
        //        $options->alipayCertPath     = '<-- 请填写您的支付宝公钥证书文件路径，例如：/foo/alipayCertPublicKey_RSA2.crt -->';
        //        $options->alipayRootCertPath = '<-- 请填写您的支付宝根证书文件路径，例如：/foo/alipayRootCert.crt" -->';
        //        $options->merchantCertPath   = '<-- 请填写您的应用公钥证书文件路径，例如：/foo/appCertPublicKey_20190521003.crt -->';
        //注：如果采用非证书模式，则无需赋值上面的三个证书路径，改为赋值如下的支付宝公钥字符串即可
        $options->alipayPublicKey = 'MIIBIjANBgkG9wQIDAQAB';
        //可设置异步通知接收服务地址（可选）

        $options->notifyUrl = WEB_URL . "/h5/payCallback/alipay/";
        //可设置AES密钥，调用AES加解密相关接口时需要（可选）
        $options->encryptKey = "5M1ZHGJHK011Q==";
        Factory::setOptions($options);
    }

    public function _pay(array $order_info, string $return_url = '', string $title = WEB_TITLE): string
    {
        $create = Factory::payment()->page()->pay($title . '-vip购买', $order_info['order_no'], $order_info['money'], $return_url);
        return $create->body;
    }

    public function _app_pay(array $order_info, string $title = WEB_TITLE): string
    {
        $create = Factory::payment()->app()->pay($title . '-vip购买', $order_info['order_no'], $order_info['money']);
        return $create->body;
    }

    public function _h5_pay(array $order_info, string $quit_url = '', string $return_url = '', string $method = 'POST', string $title = WEB_TITLE): string
    {
        $create = Factory::payment()->wap()->pay($title . '-vip购买', $order_info['order_no'], $order_info['money'], $quit_url, $return_url, $method);
        return $create->body;
    }

    public function _pay_callback(array $response)
    {
        Log::info(__METHOD__ . ':' . json_encode($response));
        try {
            $bool = Factory::payment()->common()->verifyNotify($response);
            if (!$bool) return false;
            if ($response['trade_status'] !== 'TRADE_SUCCESS') return false;
            $order_no = $response['out_trade_no'] ?? '';
            if (empty($order_no)) return false;
            // 使用通知里的 "微信支付订单号" 或者 "商户订单号" 去自己的数据库找到订单
            $order = VipOrder::getOne(['order_no' => $order_no], 'id,uid,order_no,pay_type,vip_type,status');
            // 告诉支付宝，我已经处理完了或者订单没找到，别再通知我了
            if (empty($order) || $order['status'] == PayStatus::PAY_STATUS_SUCCESS->value) return true;
            $uid = $order['uid'];
            try {
                $date_time = date('Y-m-d H:i:s');
                $where[]   = ['order_no', '=', $order_no];
                $data      = [
                    'status'   => PayStatus::PAY_STATUS_SUCCESS->value,
                    'u_time'   => $date_time,
                    'pay_time' => isset($response['send_pay_date']) ? $response['send_pay_date'] : myDate(),
                    'trade_no' => $response['trade_no'],
                ];
                VipOrder::updateDataCache($where, $data);
                $map[]     = ['uid', '=', $uid];
                $_user_vip = UserVip::getOne($map);
                if (!empty($_user_vip)) { // 已经是VIP了 时间累加
                    $_e_time = $_user_vip['e_time'];
                    if ($_e_time < $date_time) {   // VIP过期
                        $_end_time = date('Y-m-d H:i:s', strtotime("+{$order['day']} days"));
                    } else {  // 目前还是VIP
                        $_start_time = $_user_vip['e_time'];
                        $_end_time   = date("Y-m-d H:i:s", strtotime("+{$order['day']} days", strtotime($_start_time)));
                    }
                    $_data  = [
                        'u_time'   => $date_time,
                        'e_time'   => $_end_time,
                        'status'   => VipStatus::VIP_STATUS_YES->value,
                        'vip_type' => $order['vip_type'], // 续费按照最高VIP规格继续
                    ];
                    $_map[] = ['uid', '=', $uid];
                    UserVip::updateDataCache($_map, $_data);
                } else {
                    $_end_time = date('Y-m-d H:i:s', strtotime("+{$order['day']} days"));
                    $_data     = [
                        'uid'         => $uid,
                        'create_time' => time(),
                        'update_time' => time(),
                        'e_time'      => $_end_time,
                        'date_v'      => $date_time,
                        'status'      => VipStatus::VIP_STATUS_YES->value,
                        'vip_type'    => $order['vip_type'],
                    ];
                    UserVip::create($_data);
                }
                return true;    // 返回处理完成
            } catch (\PDOException $exception) {
                Log::error($exception->getMessage());
                return false;   // 让微信再来一次
            }
        } catch (RuntimeException|Exception $exception) {
            return false;
        }
    }

    /**
     * success
     * {
     * "alipay_trade_query_response": {
     * "code": "10000",
     * "msg": "Success",
     * "buyer_logon_id": "136******18",
     * "buyer_pay_amount": "0.00",
     * "buyer_user_id": "208515953171",
     * "invoice_amount": "0.00",
     * "out_trade_no": "vip1653cAZLxtX",
     * "point_amount": "0.00",
     * "receipt_amount": "0.00",
     * "send_pay_date": "2022-05-24 17:14:01",
     * "total_amount": "0.10",
     * "trade_no": "2022052105462779",
     * "trade_status": "TRADE_SUCCESS"
     * },
     * "sign": "t5lkNGtvJACIjH9w=="
     * }
     *
     * @throws Exception
     */
    public function _query(string $order_no): array
    {
        $result = Factory::payment()->common()->query($order_no);
        return json_decode($result->httpBody, true);
    }

    /**
     * @throws Exception
     */
    public function refund(array $params = []): array
    {
        $result = Factory::payment()->common()->refund($params['alipay_trade_query_response']['out_trade_no'] ?? '', $params['alipay_trade_query_response']['total_amount'] ?? 0);
        return json_decode($result->httpBody, true);
    }
}
    